import sys
import os
import re
from importlib import import_module


OperationDict = dict()
help_text = "Available parameters\n\thelp[None]:you can get some help "
INIT = True


class Operation:
    def __init__(self, name, type, help, default):
        self.name = name
        self.type = type
        self.help = help
        self.default = default
        self.func = None
        self.value = None
        self.parent = None
        self.children = set()
        OperationDict[name] = self

    def set_value(self, value):
        self.value = value

    def set_function(self, function):
        self.func = function

    def execution_function(self):
        self.func()

    def set_parent(self, parent):
        self.parent = parent

    def add_child(self, child):
        self.children.add(child)


def check_command():
    if len(sys.argv) < 2:
        print("You may need help:", sys.argv[0] + ' help')
        return False
    if sys.argv[1] == "help" or sys.argv[1] == "--help":
        print(help_text)


def get_value_to_operation(name, default):
    for index in range(len(sys.argv)):
        if "-" not in name and index < len(sys.argv) - 1 and sys.argv[index] == name:
            return sys.argv[index+1]
        if "-" in name and index < len(sys.argv) - 1 and sys.argv[index] == name:
            return " ".join(sys.argv[index+1:len(sys.argv)])
        if sys.argv[index] == name:
            return sys.argv[index]
    return default


def command(name, value_type=None, help="None", default=False):
    def decorator(func):
        if value_type is not None:
            operation = Operation(name, value_type.__name__, help, default)
        else:
            operation = Operation(name, "None", help, default)
        # 获取命令行输入值，获取不到返回默认值，有参数没有输入值则返回操作名
        value = get_value_to_operation(name, default)
        # 判断输入参数是否符合设置的参数类型
        if type(value) is not value_type and value != default and value_type is not None:
            print(f"Command parameter {name} is type of function {func.__name__}"
                  f" is incorrect, not {type(value)} should be {value_type}")
            return sys.exit(1)
        # 如果获取的值不存在则，使用默认的值，如果不需要传入值，则检测到关键字就返回结果，否则返回获取的值,如果值不存在，提示错误
        if value == default:
            operation.set_value(value)
        elif value == name:
            if value_type is None:
                operation.set_value(True)
            else:
                print(f"input of command parameter {name} is not found")
        else:
            if value_type is None:
                operation.set_value(True)
            else:
                operation.set_value(value_type(value))

        # 判断是父母操作还是孩子操作
        if name == func.__name__:
            # 父母操作指向了对应的函数
            operation.set_function(func)
            # 寻找其它操作是否是自己的孩子
            for op in OperationDict:
                op = OperationDict[op]
                if op.parent == name:
                    operation.add_child(op.name)

        else:
            # 孩子操作设置函数名为父母
            operation.set_parent(func.__name__)
            # 寻找父母
            for op in OperationDict:
                op = OperationDict[op]
                if op.name == operation.parent:
                    op.add_child(operation.name)
        return func
    return decorator


# 选择判断返回自定义函数
def get_define_function_name(text):
    command_functions = {
        "check_command": "check_command",
        "read_all_function": "read_all_function",
        "init": "init",
        "run": "run"
    }
    if command_functions.get(text, None):
        return False
    return text


# 获取用户定义德符合要求的函数
def read_all_function():
    functions = []
    current_file_name = os.path.join(os.getcwd(), sys.argv[0])
    try:
        f = open(current_file_name, "r", encoding='utf-8')
        lines = f.readlines()
    except UnicodeDecodeError:
        f = open(current_file_name, "r", encoding='gbk')
        lines = f.readlines()
    for line in lines:
        if "def" in line:
            if len(line.split("def ")) == 2 and len(line.split("def ")[1].split("()")) == 2 \
                    and re.search(r"\W", line.split("def ")[1].split("()")[0]) is None:
                function_name = line.split("def ")[1].split("()")[0]
                if get_define_function_name(function_name):
                    functions.append(function_name)
    f.close()
    return functions


def init():
    global help_text
    # for func in read_all_function():
    #     func = getattr(import_module(sys.argv[0].split(".")[0]), func)
    #     func()

    # 初始化--注入操作
    for operation in OperationDict:
        operation = OperationDict[operation]
        if operation.parent is None:
            help_text = help_text + f"\n\t{operation.name}[{operation.type}]: {operation.help}"
            if len(operation.children) > 0:
                help_text = help_text + "\n\tOptional parameters:"
            for child in operation.children:
                child_operation = OperationDict[child]
                help_text = help_text + f"\n\t\t{child_operation.name}[{child_operation.type}]:{child_operation.help}"
    check_command()


def run():
    global INIT
    init()
    INIT = False
    for operation in OperationDict:
        operation = OperationDict[operation]
        # print(operation.name, operation.value, operation.func)
        if operation.value and operation.func is not None:
            operation.execution_function()